home *** CD-ROM | disk | FTP | other *** search
- /*######################################################################################
- ## hotlist.module by Leo 'Nudel' Davidson for Gods'Gift Utilities. ##
- ## A plug-in module for Directory Opus 5.5 to provide definable file/path hotlists. ##
- ## ##
- ## ##
- ## Until July 1998 you should be able to contact me via any of the following: ##
- ## ##
- ## email: leo.davidson@keble.oxford.ac.uk ##
- ## www: http://users.ox.ac.uk/~kebl0364 ##
- ## IRC: Nudel in #Amiga on Effnet or Undernet (very rarely). ##
- ## ##
- ## Comments, suggestions, questions, offers, and chats all welcome. ##
- ## ##
- ## ##
- ## Tabsize: 4 -- 88 Columns (sorry) -- Amiga-specific -- Compile with SAS/C. ##
- ## ##
- ## Credit is due to Nick Christie, Jonathan Potter, and Greg Perry for their advice, ##
- ## examples, and general help beyond the call of duty. Thanks guys! ##
- ##************************************************************************************##
- ## There appears to be a bug in DOpus 5.5: Each call to AsyncRequestTags() looses ##
- ## 32 bytes of memory. This also happens in the example module which comes with the ##
- ## OpusSDK and has been reported to GPSoftware. ##
- ########################################################################################
- ## This program never allocates more than about 30k at a time. Since all error ##
- ## messages are output by requesters (which take quite a bit of mem to display), ##
- ## memory allocation failures result in a silent abort. Perhaps it would be better ##
- ## to at least call DisplayBeep() -- maybe in the future. ##
- ########################################################################################
- ## In order to stop one hotlist from modifying and saving config data underneath ##
- ## another a semaphore is used which blocks access to ANY config file while other ##
- ## hotlists are reading/writting. Ideally, and perhaps in the future, this locking ##
- ## would be limited to hotlists using the same config file, although at times this ##
- ## is actually an advantage. e.g. when adding a hotlist config file to another (it ##
- ## will be checked to see if it is a config file which requires openning it). ##
- ## Given that it is a rare, minor anoyance, is useful at times, and would be quite a ##
- ## pain to reliably change, I am inclinded to keep it how it is. ##
- ######################################################################################*/
-
- #include "hotlist.module.h"
-
- /**************************************************************************************/
-
- #define PROGNAME "hotlist.module"
- #define PROGVERS "1.2" // When changing this, don't forget to update the values in
- // the makefile to keep things consistent.
- #define PROGDATE __AMIGADATE__
- static char version_str[] = "\0$VER: " PROGNAME " " PROGVERS " " PROGDATE "\0";
- // Above line should be double null-terminated.
-
- /*= Definition of the module =========================================================*/
- ModuleInfo module_info =
- {
- 1, // Version
- "hotlist.module", // Module name
- "hotlist.catalog", // Catalog name
- 0, // Flags
- 1, // Number of functions
- {0,"Hotlist",MSG_HOTLIST_DESC,\
- FUNCF_SINGLE_SOURCE|FUNCF_WANT_SOURCE,\
- CMD_TEMPLATE} // First (only) function.
- };
-
- /*= Trapped Commands =================================================================*/
-
- const char *trapCmds[] =
- {
- "Delete","MakeDir","ScanDir","Duplicate",
- "Hotlist","PrintDir","DiskInfo","Copy","CopyAs","Move","MoveAs","Rename","Parent",
- "Root","Comment","Protect","Read","HexRead","Show","Play","Assign","GetSizes",
- "DateStamp"
- };
- #define TRAPPEDNUM (sizeof(trapCmds)/sizeof(const char *))
-
- /**************************************************************************************/
-
- /*= L_Module_Entry() =================================================================-.
- || Main entry point to the module. The L_ is to identify this as a library ||
- || function (specified by the "libprefix" option in the makefile) ||
- `-====================================================================================*/
- int __asm __saveds L_Module_Entry(
- register __a0 char *args, // User-supplied arguments
- register __a1 struct Screen *screen, // Screen to open on
- register __a2 IPCData *ipc, // Our IPC pointer
- register __a3 IPCData *main_ipc, // Main Opus IPC pointer
- register __d0 ULONG mod_id, // ID of module function
- register __d1 EXT_FUNC(func_callback)) // Opus callback function
- {
- Hotlist_Data *data; // Pseudo-global variables.
- FuncArgs *fa;
- ResNode *combufrn;
- struct command_packet cp;
- BYTE notsig;
-
- if (data = AllocVec(sizeof(Hotlist_Data),MEMF_CLEAR))
- {
- data->ipc = ipc;
- data->func_callback = func_callback;
- data->lister[0] = '\0';
- (data->parent)[0] = '\0';
- data->listerhandle = NULL;
- data->conflist = NULL;
-
- if (data->rnd.poolhead = NewMemHandle(PUDDLESIZE,THRESHSIZE,MEMF_CLEAR))
- {
- data->rnd.data = data;
-
- // A separate pool is used for the linked list of hotlist-entries
- // so that they can all be freed easily with one function call.
- if (data->hentspool = NewMemHandle(HEPUDDLESIZE,HETHRESHSIZE,MEMF_CLEAR))
- {
- if (DOpusBase->lib_Version < MIN_OPUS_VERSION)
- informUser(data,dgs(MSG_VERSREQ_FMT),FALSE,NULL,MIN_OPUS_VERSION);
- else if ((*((struct Library **)4))->lib_Version < MIN_EXEC_VERSION)
- informUser(data,dgs(MSG_EXECVERS_FMT),FALSE,NULL,MIN_EXEC_VERSION);
- else if (addMsgPort(data))
- {
- if ( (-1) == (notsig = AllocSignal(-1)) )
- {
- informUser(data,dgs(MSG_NOSIGS),FALSE,NULL);
- }
- else
- {
- fa = parseArgs(data,args); // Parse command-line arguments.
-
- // Setup the notify structure but don't turn it on.
- (data->notsigmask) = (1L << notsig);
- (data->notify.nr_stuff.nr_Signal.nr_SignalNum) = notsig;
- (data->notify.nr_stuff.nr_Signal.nr_Task) = FindTask(NULL);
- (data->notify.nr_Flags) = NRF_SEND_SIGNAL;
- (data->notify.nr_Name) = (data->config);
- (data->notifyon) = FALSE;
-
- readConfigFile(data,FALSE); // Parse config file.
-
- if (getListerHandle(data) && \
- (combufrn = allocNewResNode(&data->rnd,COMMBUFFSIZE)) )
- {
- basicListerInit(data,combufrn->rn_Mem,&cp);
-
- // Now setup of lister is complete and we're waiting
- // for events from the user.
-
- mainEventLoop(data,combufrn->rn_Mem,&cp);
-
- // We are no longer the active handler for the lister,
- // time to exit.
-
- deleteResNode(&data->rnd,combufrn);
- }
- notifyOff(data);
- freeArgs(fa); // Free FuncArgs structure, if any.
- FreeSignal(notsig);
- }
- remMsgPort(data);
- }
- FreeMemHandle(data->hentspool);
- data->hentspool = NULL;
- }
- // Make sure all ResourceNodes and contents freed in case of an abort.
- deleteAllResNodes(&data->rnd); // Safe to call even if no ResNodes.
- // Free our memory pool.
- FreeMemHandle(data->rnd.poolhead);
- data->rnd.poolhead = NULL;
- }
- // Free out pseudo-global variables.
- FreeVec(data);
- }
- // Currently, functions should always return 1.
- return(1);
- }
-
- /*= InformUser() =====================================================================-.
- || Send the user a requester with printf-style formatted text. ||
- || Requester is centered on the Opus screen and has just an "OK" gadget. ||
- || If window is TRUE it'll try to open over the lister window. ||
- ||------------------------------------------------------------------------------------||
- || Flags: IU_CANCEL - Adds a "Cancel" button as well as "OK". Returns boolean. ||
- `-====================================================================================*/
- long informUser(Hotlist_Data *data,char *format,BOOL window,ULONG flags,...)
- {
- long iu_return = 0;
- struct Window *win;
- struct Screen *screen;
- ResNode *rn1;
- va_list ap;
-
- if (rn1 = allocNewResNode(&data->rnd,INFORMUSERBUFFERSIZE))
- {
- // Build requester text
- va_start(ap,flags);
- vsprintf(rn1->rn_Mem,format,ap);
- va_end(ap);
-
- if (window)
- {
- win = getListerWindow(data);
- screen = NULL;
- }
- else
- {
- screen = getDOpusScreen(data);
- win = NULL;
- }
-
- // Display requester over window.
- iu_return = AsyncRequestTags(data->ipc, REQTYPE_SIMPLE, 0, 0, 0,
- TAGIF(win,AR_Window), win,
- TAGIF((!win) && screen,AR_Screen), screen,
- AR_Message, rn1->rn_Mem,
- AR_Title, dgs(MSG_TITLE),
- AR_Button, dgs(MSG_OK_GAD),
- TAGIF(flags & IU_CANCEL,AR_Button), dgs(MSG_CANCEL_GAD),
- TAG_END);
-
- deleteResNode(&data->rnd,rn1);
- }
- return(iu_return);
- }
-
- /*= GetString() ======================================================================-.
- || Send the user a string requester with printf-style formatted text. ||
- || Centred on the Opus screen unless win is TRUE. ||
- || strbuff is the buffer to put the string into, bufflen its size. ||
- || Returns the number of the button they pressed (1 for "OK", 0 for "Cancel"). ||
- ||------------------------------------------------------------------------------------||
- || Flags: As for dopus5.library/AsyncRequest() ||
- `-====================================================================================*/
- long getString(Hotlist_Data *data,char *format,BOOL window,ULONG flags,\
- char *strbuff,long bufflen,...)
- {
- long gs_return = 0;
- struct Window *win;
- struct Screen *screen;
- ResNode *rn1;
- va_list ap;
-
- if (rn1 = allocNewResNode(&data->rnd,INFORMUSERBUFFERSIZE))
- {
- // Build requester text
- va_start(ap,bufflen);
- vsprintf(rn1->rn_Mem,format,ap);
- va_end(ap);
-
- if (window)
- {
- win = getListerWindow(data);
- screen = NULL;
- }
- else
- {
- screen = getDOpusScreen(data);
- win = NULL;
- }
-
- // Display requester over window.
- gs_return = AsyncRequestTags(data->ipc, REQTYPE_SIMPLE, 0, 0, 0,
- TAGIF(win,AR_Window), win,
- TAGIF((!win) && screen,AR_Screen), screen,
- AR_Message, rn1->rn_Mem,
- AR_Title, dgs(MSG_TITLE),
- AR_Button, dgs(MSG_OK_GAD),
- AR_Button, dgs(MSG_CANCEL_GAD),
- AR_Buffer, strbuff,
- AR_BufLen, bufflen,
- AR_Flags, flags,
- TAG_END);
-
- deleteResNode(&data->rnd,rn1);
- }
- return(gs_return);
- }
-
- /*= GetPathString() ==================================================================-.
- || Send the user a string requester with printf-style formatted text. ||
- || This requester will also have a "Browse" button which replaces the string ||
- || requester with a file requester (transparent to caller -- it will be as if they ||
- || typed the selected path into the string requester, or canceled it if they cancel). ||
- || Centred on the Opus screen unless win is TRUE. ||
- || strbuff is the buffer to put the string into, bufflen its size. ||
- || Returns the number of the button they pressed (1 for "OK", 0 for "Cancel"). ||
- ||------------------------------------------------------------------------------------||
- || Flags: As for dopus5.library/AsyncRequest() ||
- `-====================================================================================*/
- long getPathString(Hotlist_Data *data,char *format,BOOL window,ULONG flags,\
- char *strbuff,long bufflen,...)
- {
- long gs_return = 0;
- struct Window *win;
- struct Screen *screen;
- ResNode *rn1;
- va_list ap;
- APTR req;
- char *fpath;
-
- if (rn1 = allocNewResNode(&data->rnd,INFORMUSERBUFFERSIZE))
- {
- // Build requester text
- va_start(ap,bufflen);
- vsprintf(rn1->rn_Mem,format,ap);
- va_end(ap);
-
- if (window)
- {
- win = getListerWindow(data);
- screen = NULL;
- }
- else
- {
- screen = getDOpusScreen(data);
- win = NULL;
- }
-
- // Display requester over window.
- gs_return = AsyncRequestTags(data->ipc, REQTYPE_SIMPLE, 0, 0, 0,
- TAGIF(win,AR_Window), win,
- TAGIF((!win) && screen,AR_Screen), screen,
- AR_Message, rn1->rn_Mem,
- AR_Title, dgs(MSG_TITLE),
- AR_Button, dgs(MSG_OK_GAD),
- AR_Button, dgs(MSG_BROWSE_GAD),
- AR_Button, dgs(MSG_CANCEL_GAD),
- AR_Buffer, strbuff,
- AR_BufLen, bufflen,
- AR_Flags, flags,
- TAG_END);
-
- // If they selected "browse":
- if (gs_return == 2)
- {
- gs_return = 0;
-
- if (req = AllocAslRequestTags(ASL_FileRequest,
- TAGIF(win,ASLFR_Window), win,
- TAGIF((!win) && screen,ASLFR_Screen), screen,
- ASLFR_InitialDrawer, "SYS:",
- TAG_END))
- {
- if (gs_return = AslRequestTags(req,TAG_END))
- {
- fpath = stpcpy(strbuff,((struct FileRequester *)req)->fr_Drawer);
-
- // If there was a path string and it didn't end in "/" or ":",
- // insert a "/" before the filename.
-
- if ( (((struct FileRequester *)req)->fr_Drawer[0]) && \
- (fpath[-1] != ':') && (fpath[-1] != '/') )
- {
- fpath = stpcpy(fpath,"/");
- }
- stpcpy(fpath,((struct FileRequester *)req)->fr_File);
- }
- FreeAslRequest(req);
- }
- }
-
- deleteResNode(&data->rnd,rn1);
- }
- return(gs_return);
- }
-
- /*= getListerHandle() ================================================================-.
- || Fills in data->lister & data->listerhandle with handle of the lister we're to use. ||
- || If there is no source lister, or the NEW argument was given, a new lister is ||
- || transparently created. ||
- || data->parent will be set to the path of the old lister, or to the empty string if ||
- || a new lister was created or the path was unobtainable. ||
- ||------------------------------------------------------------------------------------||
- || If data->lister and data->listerhandle are already set (by the command-line parse) ||
- || they will be left, but data->parent will still be filled in. ||
- ||------------------------------------------------------------------------------------||
- || data->lister and data->parent *MUST* be set to the empty string before calling ||
- || the command-line parser and then this routine. ||
- ||------------------------------------------------------------------------------------||
- || Returns boolean success. ||
- `-====================================================================================*/
- BOOL getListerHandle(Hotlist_Data *data)
- {
- BOOL glh_return = FALSE;
- ResNode *combufrn;
- struct command_packet cp;
-
- // Allocate a command buffer.
- if (combufrn = allocNewResNode(&data->rnd,COMMBUFFSIZE))
- {
- struct path_node *pn;
-
- // If they didn't give the "NEW" switch, first attempt to get the
- // source lister, unless we already have one (from command-line).
- if ( (!(data->new)) && ((data->lister)[0] == '\0') )
- {
- // Killing two birds with one stone, get the old path into data->parent
- // and get a pointer to the structure with the wanted lister handle, too.
- // If the lister handle is NULL, we'll have to get a new one (this will
- // if they press run us from the toolbar of a devicelist lister).
- if ((pn = (struct path_node *)data->func_callback(EXTCMD_GET_SOURCE,\
- IPCDATA(data->ipc),data->parent)) && \
- (pn->lister))
- {
- glh_return = TRUE; // We got one! -- Convert long to ASCII.
- stcl_d(data->lister,(long)(pn->lister));
- }
- }
- // If the lister handle was given on the command-line, get the path from it.
- else if (!(data->new))
- {
- sprintf(combufrn->rn_Mem,"lister query %s path",data->lister);
- cp.flags = COMMANDF_RESULT;
- cp.command = combufrn->rn_Mem;
- cp.result = NULL;
- if ((data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),&cp)) && \
- (cp.result) && (cp.result[0]))
- {
- strcpy(data->parent,cp.result);
- }
-
- if (cp.result)
- {
- FreeVec(cp.result);
- cp.result = NULL;
- }
-
- glh_return = TRUE; // We got one!
- }
-
- // If any source listers are locked now, unlock them. (Even if we're going to
- // use one of the source listers as it'll be made busy again shortly).
-
- data->func_callback(EXTCMD_UNLOCK_SOURCE,IPCDATA(data->ipc),NULL);
-
-
- // If there still isn't a lister handle, either "NEW" was given or we
- // couldn't get a source lister, so open a new one.
- if ((data->lister)[0] == '\0')
- {
- // Just incase it was wrongly set TRUE in the get-source part.
- glh_return = FALSE;
-
- // "lister new" command string, with or without snapshot geometry.
- if ( ((data->snap.x) == (-1)) && ((data->snap.y) == (-1)) && \
- ((data->snap.w) == (-1)) && ((data->snap.h) == (-1)) )
- {
- cp.command = "lister new";
- }
- else
- {
- sprintf(combufrn->rn_Mem,"lister new %d/%d/%d/%d",
- data->snap.x,data->snap.y,data->snap.w,data->snap.h);
- cp.command = combufrn->rn_Mem;
- }
- cp.flags = COMMANDF_RESULT; // We do want a result.
- // Send the command.
- if ( (data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),&cp)) && \
- ((cp.rc) == 0) && (cp.result) && (*(cp.result)) )
- {
- strcpy(data->lister,cp.result); // Store the handle string.
- FreeVec(cp.result); // Free the result string's mem.
- glh_return = TRUE; // We got one!
- }
- }
-
- deleteResNode(&data->rnd,combufrn);
- }
-
- if (glh_return)
- {
- // If we got a lister handle in the end, store an APTR version of it, too.
- (data->listerhandle) = (APTR)(atol(data->lister));
- }
-
- return(glh_return);
- }
-
- /*= sendExtCmd_nr() ==================================================================-.
- || Function to make calling Opus ARexx commands slightly cleaner. This version for ||
- || when you do not want a result string. ||
- `-====================================================================================*/
- void sendExtCmd_nr(Hotlist_Data *data,char *cmdstring,struct command_packet *cpp)
- {
- // We do NOT want a result, but dopus5.library seems prone to
- // memory leaks when one isn't requested for certain commands,
- // so we'll ask for one and free it immediately afterwards.
- cpp->flags = COMMANDF_RESULT;
- cpp->command = cmdstring;
- data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),cpp);
- FreeVec(cpp->result);
- cpp->result = NULL;
- }
-
- /*= addEntries() =====================================================================-.
- || Add the entries in the linked list of HotEntry structures to the lister. ||
- || Does not refresh the lister. ||
- `-====================================================================================*/
- void addEntries(Hotlist_Data *data,char *combuf,struct command_packet *cpp)
- {
- HotEntry *hep;
-
- if (data->hentbase)
- {
- for (hep = data->hentbase; hep; hep = hep->next)
- {
- // We do NOT want a result, but dopus5.library seems prone to
- // memory leaks when one isn't requested for certain commands,
- // so we'll ask for one and free it immediately afterwards.
- // (Haven't used sendExtCmd_nr for some extra speed here.)
- cpp->flags = COMMANDF_RESULT;
- cpp->command = combuf;
- sprintf(combuf,"lister add %s \"%s\" 0 %d 0 rwed (%s)",
- data->lister,hep->name,hep->type,hep->path);
- data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),cpp);
- FreeVec(cpp->result);
- cpp->result = NULL;
- }
- }
- else
- {
- // Otherwise add a default entry saying "Empty: drop here" type thing.
- sprintf(combuf,"lister add %s \"%s\" 0 %d 0 rwed (%s)",
- data->lister,dgs(MSG_DEFAULTNAME),-2,dgs(MSG_DEFAULTPATH));
- sendExtCmd_nr(data,combuf,cpp);
- }
- }
-
- /*= mainEventLoop() ==================================================================-.
- || Once the lister is setup, this loops around until an inactive event, dealing with ||
- || the events the user throws at it. ||
- `-====================================================================================*/
- void mainEventLoop(Hotlist_Data *data,char *combuf,struct command_packet *cpp)
- {
- struct StandardPacket *pkt;
- ULONG msgsigmask;
- ULONG signals;
- BOOL stoploop = FALSE;
- char *a0;
- char *a1;
- char *a2;
- char *a3;
- char *a4;
- char *a5;
- char *a6;
-
- msgsigmask = (1L << (data->msgport->mp_SigBit));
-
- while(TRUE)
- {
- signals = Wait((data->notsigmask) | (msgsigmask));
-
- // If we got a notification request, re-read the config.
- if (signals & (data->notsigmask))
- rereadConfig(data,combuf,cpp);
-
- // If there may be one or more messages on our port, process them.
- if (signals & msgsigmask)
- {
- while ((!stoploop) && (pkt=(struct StandardPacket *)GetMsg(data->msgport)))
- {
- // Note that the arg?'s start from 0 to sync with Opus ARexx Guide.
- a0 = (char *)pkt->sp_Pkt.dp_Arg1;
- a1 = (char *)pkt->sp_Pkt.dp_Arg2;
- a2 = (char *)pkt->sp_Pkt.dp_Arg3;
- a3 = (char *)pkt->sp_Pkt.dp_Arg4;
- a4 = (char *)pkt->sp_Pkt.dp_Arg5;
- a5 = (char *)pkt->sp_Pkt.dp_Arg6;
- a6 = (char *)pkt->sp_Pkt.dp_Arg7;
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- if (strcmp(a0,"inactive") == 0)
- {
- stoploop = event_inactive(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"doubleclick") == 0)
- {
- stoploop = event_doubleclick(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"dropfrom") == 0)
- {
- stoploop = event_dropfrom(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"drop") == 0)
- {
- stoploop = event_drop(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"MakeDir") == 0)
- {
- stoploop = event_makedir(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"Delete") == 0)
- {
- stoploop = event_delete(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"path") == 0)
- {
- stoploop = event_path(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if ((strcmp(a0,"ScanDir") == 0) || (strcmp(a0,"Hotlist") == 0))
- {
- stoploop = event_scandir_hotlist(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"snapshot") == 0)
- {
- stoploop = event_snapshot(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"unsnapshot") == 0)
- {
- stoploop = event_unsnapshot(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"Rename") == 0)
- {
- stoploop = event_rename(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"parent") == 0)
- {
- stoploop = event_parent(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else if (strcmp(a0,"Duplicate") == 0)
- {
- stoploop = event_duplicate(data,combuf,cpp,a1,a2,a3,a4,a5,a6);
- }
- else
- {
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
- informUser(data,dgs(MSG_UNSUPPORTED_FMT),TRUE,0,a0);
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
- }
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- ReplyMsg((struct Message *)pkt);
- }
- if (stoploop) break;
- }
- }
- }
-
- /*= writeConfigFile() ================================================================-.
- || Attempts to write the current entry data to the config file. If anything fails an ||
- || error requester will probably be shown to the user, but there is no return result; ||
- || the rest of the program should continue even if the config file couldn't be ||
- || written. ||
- ||------------------------------------------------------------------------------------||
- || Before the write happens, notification will be turned off (if on), and then back ||
- || on again after the write. ||
- ||------------------------------------------------------------------------------------||
- || Before calling this you **MUST** get an exclusive lock on the config semaphore. ||
- || After calling this you must release the lock, unless you still need it. ||
- || You should use getWriteConfigSemaphore() for locking -- see that for more info. ||
- `-====================================================================================*/
- void writeConfigFile(Hotlist_Data *data)
- {
- BOOL ifffailed = FALSE;
- HotEntry *hent;
- APTR iffhandle;
- int confver;
-
- confver = CONFIGVER;
-
- notifyOff(data);
-
- // Even if there are no hotlist entries, we should still write the config file
- // because it also contains snapshot information (and maybe more in the future).
-
- if (iffhandle = IFFOpen(data->config,IFF_WRITE|IFF_SAFE,ID_DOHL))
- {
- if ( (!(IFFWriteChunk(iffhandle,&confver,ID_VERS,sizeof(int)))) || \
- (!(IFFWriteChunk(iffhandle,&data->snap,ID_SNAP,sizeof(data->snap)))) || \
- (!(IFFWriteChunk(iffhandle,&data->time,ID_TIME,sizeof(data->time)))) )
- ifffailed = TRUE;
-
- for (hent = data->hentbase; (!ifffailed) && hent; hent = hent->next)
- {
- // Only save the entry if it hasn't been marked for deletion.
- if (!(hent->deleted))
- {
- // The NAME field must always be first as it is used when reading
- // the config file to designate the start of each new entry.
- if ((!IFFWriteChunk(iffhandle,hent->name,ID_NAME,strlen(hent->name)+1))\
- || (!IFFWriteChunk(iffhandle,hent->path,ID_PATH,strlen(hent->path)+1))\
- || (!IFFWriteChunk(iffhandle,&hent->type,ID_TYPE,sizeof(hent->type))) )
- {
- ifffailed = TRUE;
- }
- }
- }
-
- if (ifffailed)
- {
- informUser(data,dgs(MSG_CONFIGWRITE_ERROR),TRUE,NULL);
- IFFFailure(iffhandle);
- }
-
- IFFClose(iffhandle);
- }
- else
- {
- informUser(data,dgs(MSG_CONFIGWRITE_ERROR),TRUE,NULL);
- }
-
- notifyOn(data);
- }
-
- /*= readConfigFile() =================================================================-.
- || Attempts to replace the existing config (if any) in memory with that stored in the ||
- || config file. ||
- || If the config file could not be read, hentbase will be NULL and the snapshot ||
- || position will be disabled (all -1). This will happen when the user hasn't yet ||
- || made a hotlist, for example, as well as when there is a genuine error. ||
- ||------------------------------------------------------------------------------------||
- || Before the read happens, notification will be turned off (if on), and then back ||
- || on again after the read. ||
- ||------------------------------------------------------------------------------------||
- || Will wait until it can get a shared lock on the config semaphore. ||
- || Set alreadylocked to TRUE if we already have an exclusive lock on the semaphore ||
- || (e.g. if this routine is called once we get exclusive access to the config file ||
- || but the file needs re-reading as it has changed). Should never call this routine ||
- || with a shared lock on the semaphore. ||
- `-====================================================================================*/
- void readConfigFile(Hotlist_Data *data,BOOL alreadylocked)
- {
- BOOL iffsucc;
- HotEntry *chent;
- ULONG chunkid;
- APTR iffhandle;
- struct ClockData newtime;
- ULONG tsecs;
- ULONG tmics;
-
- iffsucc = FALSE;
-
- CurrentTime(&tsecs,&tmics);
- Amiga2Date(tsecs,&newtime);
-
- // Default geometry for new lister. -1 for all means "not snapshotted".
- data->snap.x = data->snap.y = data->snap.w = data->snap.h = -1;
-
- data->time.sec = newtime.sec;
- data->time.min = newtime.min;
- data->time.hour = newtime.hour;
- data->time.mday = newtime.mday;
- data->time.month = newtime.month;
- data->time.year = newtime.year;
- data->time.wday = newtime.wday;
-
- notifyOff(data);
-
- // Get a shared lock on our semaphore.
- if (!(alreadylocked))
- getConfigSemaphore(data,GCS_SHARED);
-
- if (iffhandle = IFFOpen(data->config,IFF_READ,ID_DOHL))
- {
- iffsucc = TRUE;
- chent = NULL;
- while ((iffsucc) && (chunkid = IFFNextChunk(iffhandle,0)))
- {
- // The NAME chunk designates a new hotlist entry.
- if ((chunkid == ID_NAME) && (chent = newHotEntry(data)))
- iffsucc = IFFReadChunkBytes(iffhandle,chent->name,sizeof(chent->name));
- else if ((chent) && (chunkid == ID_PATH))
- iffsucc = IFFReadChunkBytes(iffhandle,chent->path,sizeof(chent->path));
- else if ((chent) && (chunkid == ID_TYPE))
- iffsucc = IFFReadChunkBytes(iffhandle,&chent->type,sizeof(chent->type));
- else if (chunkid == ID_SNAP)
- iffsucc = IFFReadChunkBytes(iffhandle,&data->snap,sizeof(data->snap));
- else if (chunkid == ID_TIME)
- iffsucc = IFFReadChunkBytes(iffhandle,&data->time,sizeof(data->time));
- }
- IFFClose(iffhandle);
- }
-
- if (!iffsucc)
- {
- if (IoErr() != ERROR_OBJECT_NOT_FOUND)
- informUser(data,dgs(MSG_CONFIGREAD_ERROR),TRUE,NULL);
-
- // Default geometry for new lister. -1 for all means "not snapshotted".
- data->snap.x = data->snap.y = data->snap.w = data->snap.h = -1;
-
- data->hentbase = NULL; // Make sure hentbase is NULL.
- ClearMemHandle(data->hentspool); // Free all hotentry memory (pool remains).
- }
-
- // The semaphore must be released NOW as splent() below may want to write
- // to the config file (attempting an EXCLUSIVE lock), which would cause a
- // deadlock otherwise.
- if (!(alreadylocked))
- ReleaseSemaphore(configsemaphore);
-
- notifyOn(data);
-
- if ((newtime.mday != data->time.mday) || (newtime.month != data->time.month))
- {
- if ((newtime.mday == 25) && (newtime.month == 12))
- splent(data,alreadylocked,&newtime,"Nfssz Disjtunbt!");
- else if ((newtime.mday == 1) && (newtime.month == 1))
- splent(data,alreadylocked,&newtime,"Ibqqz Ofx Zfbs!");
- else if ((newtime.mday == 20) && ((newtime.month)%3 == 0))
- splent(data,alreadylocked,&newtime,
- "Ifz, opu tp gbtu. J'n tjdl pg cfjoh vtfe,\n" \
- "zpv bmxbzt kvtu pqfo nf vq, dipptf b\n" \
- "ejsfdupsz, boe uifo J'n hpof. Zpv ofwfs\n" \
- "ubml up nf. Ebnnju, zpv usfbu nf mjlf ejsu.\n" \
- "Jg zpv epo'u tubsu qbzjoh nf npsf buufoujpo,\n" \
- "J njhiu kvtu hp po tusjlf. Zfbi, tff ipx\n" \
- "uibu nblft zpv gffm. Qsphsbnt ibwf sjhiut\n" \
- "zpv lopx, tp, jo uif gvuvsf, cf ojdf.");
- else if ((newtime.mday == 29) && (newtime.month == 2))
- splent(data,alreadylocked,&newtime,
- "29ui pg Gfcsvbsz.\n" \
- "Zpv epo'u tff nboz pg uiptf...");
- else if ((newtime.mday == 7) && (newtime.month == 1))
- splent(data,alreadylocked,&newtime,
- "Upebz jt uif cjsuiebz pg nz dsfbups, Mfp Ebwjetpo.\n" \
- "Zpv sfbmmz tipvme tfoe ijn b hjgu, if't b usvfmz\n" \
- "xpoefsgvm qfstpo boe J pxf fwfszuijoh up ijn. :-)\n" \
- "Bu mfbtu tfoe bo fnbjm (cfgpsf Kvmz 1998) up ijn:\n\n" \
- "mfp.ebwjetpo@lfcmf.pygpse.bd.vl");
- else if ((newtime.mday == 9) && (newtime.month == 7))
- splent(data,alreadylocked,&newtime,
- "J ibwf up ufmm zpv tpnfuijoh.\n\n" \
- "J lopx J'n pomz b ipumjtu, cvu usvf mpwf\n" \
- "lopxt op cpvoet. Zft -- J mpwf zpv. J ibwf\n" \
- "bmxbzt mpwfe zpv tjodf uif ebz zpv gjstu\n" \
- "jotfsufe zpvs fousjft joup nf. Opx J dboopu\n" \
- "lffq uiftf gffmjoht up nztfmg boznpsf.");
- else if ((newtime.mday == 15) && (newtime.month == 4))
- splent(data,alreadylocked,&newtime,
- "J bn Ipumjtuipmjp.\n" \
- "J offe UQ gps nz cvohipmf.\n\n" \
- "Bsf zpv uisfbufojoh nf?\n" \
- "ZPV XJMM HJWF NF UQ, CVOHIPMJP!\n\n" \
- "...xifsf J dpnf gspn uifz ibwf op cvohipmft...");
- else if ((newtime.mday == 15) && (newtime.month == 8))
- splent(data,alreadylocked,&newtime,"CPP!\n\n(Eje J tdbsf zpv?)");
- else if ((newtime.mday == 12) && (newtime.month == 10))
- splent(data,alreadylocked,&newtime,
- "Boe xibu jg J epo'u xbou up cf b ipumjtu upebz?");
- }
- }
-
- /*= splent() =========================================================================-.
- || A harmless surprise every so often. :-) (Don't spoil the fun and tell everyone!) ||
- `-====================================================================================*/
- void splent(Hotlist_Data *data,BOOL alreadylocked,struct ClockData *newtime,char *msg)
- {
- char c;
- char *p;
- ResNode *memrn;
-
- if (memrn = allocNewResNode(&data->rnd,4096))
- {
- if (!(alreadylocked))
- getWriteConfigSemaphore(data);
-
- data->time.sec = newtime->sec;
- data->time.min = newtime->min;
- data->time.hour = newtime->hour;
- data->time.mday = newtime->mday;
- data->time.month = newtime->month;
- data->time.year = newtime->year;
- data->time.wday = newtime->wday;
-
- p = memrn->rn_Mem;
-
- // Not exactly PGP, I know. :-) Does the job, though.
- while(c = *msg++)
- {
- if (isalpha(c))
- {
- if (c == 'A')
- c = 'Z';
- else if (c == 'a')
- c = 'z';
- else
- c--;
- }
- *p++ = c;
- }
- *p = '\0';
-
- informUser(data,memrn->rn_Mem,FALSE,NULL);
-
- writeConfigFile(data); // Don't do this one again ('till next year).
- if (!(alreadylocked))
- ReleaseSemaphore(configsemaphore);
-
- deleteResNode(&data->rnd,memrn);
- }
- }
-
- /*= rereadConfig() ===================================================================-.
- || Clears all entries from the lister, frees all HotEntries, reloads the config file ||
- || and adds the entries to the lister. ||
- ||------------------------------------------------------------------------------------||
- || This routien MUST do a full refresh on the lister, even if it doesn't require it ||
- || itself in the future as at least two other routines (at this time) depend on it. ||
- `-====================================================================================*/
- void rereadConfig(Hotlist_Data *data,char *combuf,struct command_packet *cpp)
- {
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- // Note that this is "clear", not "empty" like in the initial setup.
- sprintf(combuf,"lister clear %s",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- data->hentbase = NULL; // Make sure hentbase is NULL.
- ClearMemHandle(data->hentspool); // Free all hotentry memory (pool remains).
-
- readConfigFile(data,FALSE);
- addEntries(data,combuf,cpp);
-
- sprintf(combuf,"lister refresh %s full",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
- }
-
- /*= newHotEntry() ====================================================================-.
- || Allocate a new HotEntry structure, add it to the linked list, and give it some ||
- || default values. Returns NULL on failure. ||
- `-====================================================================================*/
- HotEntry *newHotEntry(Hotlist_Data *data)
- {
- HotEntry *nhe;
-
- if (nhe = AllocMemH(data->hentspool,sizeof(HotEntry)))
- {
- // Add to front of linked list.
- (nhe->next) = (data->hentbase);
- (data->hentbase) = nhe;
-
- // Give it some defaults, just in case the config file is old or invalid
- // and doesn't define them. There's little point in localizing these as
- // they should never really be seen.
- strcpy(nhe->name,"--errname--");
- strcpy(nhe->path,"--errpath--");
- (nhe->type) = (-1);
- (nhe->deleted) = FALSE;
- }
-
- return(nhe);
- }
-
- /*= remHotEntry() ====================================================================-.
- || Remove and deallocate the most recently added HotEntry structure. ||
- `-====================================================================================*/
- void remHotEntry(Hotlist_Data *data)
- {
- HotEntry *ohe;
-
- if (data->hentbase)
- {
- ohe = (data->hentbase);
- (data->hentbase) = (ohe->next);
-
- FreeMemH((APTR) ohe);
- }
- }
-
- /*= wordcpy() ========================================================================-.
- || Copy the string from source to dest until the first quote or NULL in source. ||
- || source will be advanced to point to the character after the second quote if there ||
- || is one, or the NULL terminator otherwise. ||
- `-====================================================================================*/
- void wordcpy(char *dest,char **source)
- {
- while((**source) && (**source != '"'))
- *(dest++) = *((*source)++);
- *dest = '\0';
-
- if (**source == '"')
- {
- (*source)++;
- if (**source == ' ')
- {
- (*source)++;
- if (**source == '"')
- (*source)++;
- }
- }
- }
-
- /*= wordCount() ======================================================================-.
- || Counts the number of quote characters in the string, divides by two, and returns ||
- || the number. ||
- `-====================================================================================*/
- int wordcount(char *wordstring)
- {
- int wcnt = 0;
-
- if (wordstring)
- {
- while(*wordstring)
- {
- if (*(wordstring++) == '"')
- wcnt++;
- }
-
- wcnt /= 2;
- }
-
- return(wcnt);
- }
-
- /*= findHotEntry() ===================================================================-.
- || Searches along the HotEntries linked list until it finds one which has the same ||
- || name as that given. Returns NULL if there is no match. ||
- || Will not match entries which have been marked as "deleted". ||
- || The match is *not* case-sensitive. ||
- `-====================================================================================*/
- HotEntry *findHotEntry(Hotlist_Data *data,char *searchname)
- {
- HotEntry *he;
-
- for (he = (data->hentbase); he; he = he->next)
- {
- if ((!(he->deleted)) && (stricmp(he->name,searchname) == 0))
- break;
- }
-
- return(he);
- }
-
- /*= findOldEntry() ===================================================================-.
- || Searches along the HotEntries linked list until it finds one which has the same ||
- || name as that given. Returns TRUE if there's a match which isn't the most recently ||
- || added entry, FALSE otherwise. ||
- || Will not match entries which have been marked as "deleted". ||
- || The match is *not* case-sensitive. ||
- `-====================================================================================*/
- BOOL findOldEntry(Hotlist_Data *data,char *searchname)
- {
- HotEntry *he = NULL;
-
- if ((data->hentbase) && (data->hentbase->next))
- {
- for (he = (data->hentbase->next); he; he = he->next)
- {
- if ((!(he->deleted)) && (stricmp(he->name,searchname) == 0))
- break;
- }
- }
-
- return((BOOL)he);
- }
-
- /*= setHotType() =====================================================================-.
- || Based on the path of the given HotEntry, sets the type of the entry. ||
- || If it can't work it out it'll default to being a directory. ||
- || Those entries recognised as files may be openned and checked to see if they're ||
- || hotlist.module config files (which have their own type). ||
- `-====================================================================================*/
- void setHotType(Hotlist_Data *data,HotEntry *nhe)
- {
- ResNode *bufrn;
- ResNode *rn;
- char *buf;
- BPTR lock;
- APTR iffhandle;
-
- // Default to the directory type if anything fails.
- (nhe->type) = HOTTYPE_DIR;
-
- if (bufrn = allocNewResNode(&data->rnd,PATHBUFFSIZE))
- {
- buf = (char *)bufrn->rn_Mem;
- if (rn = createResNode(&data->rnd))
- {
- (rn->rn_Name) = (nhe->path);
- if (lock = lockFileResNode(&data->rnd,rn,ACCESS_READ))
- {
- if ( (NameFromLock(lock,buf,PATHBUFFSIZE)) && \
- ( buf[strlen(buf)-1] == ':') )
- {
- (nhe->type) = HOTTYPE_DEV;
- }
- else if ( (examineResNode(&data->rnd,rn)) && \
- ((rn->rn_FIB->fib_DirEntryType) < 0) )
- {
- // It's a file -- see if it matches the hotlist.module
- // IFF config type. If so it gets the special HOTTYPE_HOT type.
- if (iffhandle = IFFOpen(rn->rn_Name,IFF_READ,ID_DOHL))
- {
- IFFClose(iffhandle);
- (nhe->type) = HOTTYPE_HOT;
- }
- else
- (nhe->type) = HOTTYPE_FILE;
- }
- else
- {
- (nhe->type) = HOTTYPE_DIR;
- }
- }
- else
- {
- // If we cannot lock the file, assume it doesn't exist and
- // call it a new hotlist.
- (nhe->type) = HOTTYPE_HOT;
- }
- deleteResNode(&data->rnd,rn);
- }
- deleteResNode(&data->rnd,bufrn);
- }
- }
-
- /*= getListerWindow() ================================================================-.
- || Gets the window of a lister from just the lister handle (in ASCII). ||
- || Returns the handle, or NULL. This should not be stored for later use as the window ||
- || may be different next time (for example, Opus has reopenned on another screen). ||
- || This is a bit of a hack, but Jonathan Potter has said it should be okay. ||
- `-====================================================================================*/
- struct Window *getListerWindow(Hotlist_Data *data)
- {
- struct path_node pn;
- struct Window *win = NULL;
-
- if (data->listerhandle)
- {
- // Setup some semi-sensible defaults (and hope they'll do!)
- pn.buffer[0] = '\0';
- pn.path = pn.buffer;
- pn.flags = NULL;
-
- pn.lister = (data->listerhandle);
-
- win = (struct Window *)\
- data->func_callback(EXTCMD_GET_WINDOW,IPCDATA(data->ipc),(APTR)&pn);
- }
- return(win);
- }
-
- /*= getDOpusScreen() =================================================================-.
- || Attempts to get the Opus screen, returns it or NULL. ||
- || The return should not be stored for later use as the screen may be different next ||
- || time if the user has changed it. ||
- `-====================================================================================*/
- struct Screen *getDOpusScreen(Hotlist_Data *data)
- {
- struct Screen *screen = NULL;
- struct DOpusScreenData *dsd;
-
- if (dsd = (struct DOpusScreenData *)\
- data->func_callback(EXTCMD_GET_SCREENDATA,IPCDATA(data->ipc),NULL))
- {
- screen = dsd->screen;
-
- data->func_callback(EXTCMD_FREE_SCREENDATA,IPCDATA(data->ipc),(APTR)dsd);
- }
- return(screen);
- }
-
- /*= listerRead() =====================================================================-.
- || Restores the original lister settings and then reads the given path in. ||
- ||------------------------------------------------------------------------------------||
- || **IMPORTANT** This routine removes our handler from the lister. After calling we ||
- || ************* should shutdown. ||
- `-====================================================================================*/
- void listerRead(Hotlist_Data *data,char *combuf,struct command_packet *cpp,char *path)
- {
- sprintf(combuf,"lister clear %s",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s handler",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s lock state %s format %s",data->lister,"off","off");
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s namelength %d",data->lister,31);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister empty %s",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s field %s",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister refresh %s full",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister read %s \"%s\"",data->lister,path);
- sendExtCmd_nr(data,combuf,cpp);
- }
-
- /*= parseArgs() ======================================================================-.
- || Parses command-line arguments and sets the "NEW" switch and "CONFIG" file name. ||
- || If there is no command-line, or some kind of error/problem occurs during parsing, ||
- || defaults will be used. ||
- `-====================================================================================*/
- FuncArgs *parseArgs(Hotlist_Data *data,char *args)
- {
- FuncArgs *fa;
-
- // Defaults.
- (data->new) = FALSE;
- (data->config) = DEFAULT_CONFIG;
-
- if (fa = ParseArgs(CMD_TEMPLATE,args))
- {
- (data->new) = (BOOL)((fa->FA_Arguments)[ARG_NEW]);
-
- if ((fa->FA_Arguments)[ARG_CONFIG])
- {
- (data->config) = (char *)((fa->FA_Arguments)[ARG_CONFIG]);
- }
-
- if ( ((fa->FA_Arguments)[ARG_LISTER]) &&
- (strlen((char *)((fa->FA_Arguments)[ARG_LISTER])) < 24) )
- {
- strcpy(data->lister,(char *)((fa->FA_Arguments)[ARG_LISTER]));
- }
- }
-
- (data->originalconfig) = (data->config);
-
- return(fa);
- }
-
- /*= freeArgs() =======================================================================-.
- || Frees the structure returned by parseArgs(), if one returned at all. ||
- || All pointers into the structure will be invalid after this call. ||
- `-====================================================================================*/
- void freeArgs(FuncArgs *fa)
- {
- if (fa)
- DisposeArgs(fa);
- }
-
- /*= endcpy() =========================================================================-.
- || Copies the source string to the dest string (of length destlen). If the dest is ||
- || too small it'll chop off enough characters from the source to make the END of it ||
- || fit in. ||
- `-====================================================================================*/
- void endcpy(char *dest,char *source,long destlen)
- {
- long diff;
-
- diff = strlen(source) - (destlen-1);
-
- if (diff > 0)
- source += diff;
-
- strcpy(dest,source);
- }
-
- /*= leofilepart() ====================================================================-.
- || Calls dos.library/FilePart() on the string and returns the result if non-empty, ||
- || otherwise it returns the original string. Only (intended) difference is that if ||
- || you pass a device string like "DH0:" it won't return the empty string, it'll ||
- || return "DH0:". ||
- `-====================================================================================*/
- char *leofilepart(char *path)
- {
- char *lfp;
-
- lfp = FilePart(path);
-
- if (lfp[0] == '\0')
- lfp = path;
-
- return(lfp);
- }
-
- /*= notHandled() =====================================================================-.
- || Returns: ||
- || >0 if there is no handler attached to the lister handle given (ASCII), or the ||
- || lister handle given is the empty string (e.g. drop not from a lister). ||
- || 0 if there is a hotlist handler attached which is not our one. ||
- || <0 if there is either a non-hotlist handler or our hotlist handler attached. ||
- || ||
- || When there is a non-hotlist handler attached it puts up an error requester saying ||
- || something along the lines of "You cannot drop entries between a Hotlist and ||
- || another custom-handler driven lister." ||
- || ||
- || In certain situations where a drop didn't go to/come from a lister at all, the ||
- || handle Opus returns is ours instead of empty (AFAIK this only happens when you ||
- || drop from our lister to the main Opus window). To bypass this situation, if the ||
- || lister handle string is the same as data->lister, <0 will still be returned, ||
- || (since we still want to ignore the event), but instead of the error message being ||
- || shown, DisplayBeep() will be called. ||
- `-====================================================================================*/
- LONG notHandled(Hotlist_Data *data,char *combuf,struct command_packet *cpp,char *lh)
- {
- LONG nh_return = 1;
-
- if ((lh) && (lh[0]))
- {
- // If it's our lister, complain with a DisplayBeep and send back -1.
- if (strcmp(lh,data->lister) == 0)
- {
- nh_return = (-1);
- DisplayBeep(NULL);
- }
- else
- {
- sprintf(combuf,"lister query %s handler",lh);
- cpp->flags = COMMANDF_RESULT;
- cpp->command = combuf;
- cpp->result = NULL;
- if ((data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),cpp)) && \
- (cpp->result) && (cpp->result[0] != '\0'))
- {
- if (strncmp(cpp->result,PORTNAME_PREFIX,strlen(PORTNAME_PREFIX))
- == 0)
- {
- // If it's another hotlist handler, return 0.
- nh_return = 0;
- }
- else
- {
- // If it's a handler but not a hotlist one, return -1.
- nh_return = (-1);
- informUser(data,dgs(MSG_NOCUSTDROP),TRUE,0);
- }
- }
- // else, leave it as 1.
-
- if (cpp->result)
- {
- FreeVec(cpp->result);
- cpp->result = NULL;
- }
- }
- }
- return(nh_return);
- }
-
- /*= addMsgPort() =====================================================================-.
- || Creates a message port with unique name and adds it to the port list. ||
- `-====================================================================================*/
- BOOL addMsgPort(Hotlist_Data *data)
- {
- BOOL amp_return = FALSE;
- int pnum;
-
- if (data->msgport = CreateMsgPort())
- {
- (data->msgport->mp_Node.ln_Pri) = 2;
- (data->msgport->mp_Node.ln_Name) = (data->mpname);
-
- pnum = 0;
- Forbid();
- do
- {
- sprintf(data->mpname,PORTNAME_FMT,pnum);
- pnum++;
- } while (FindPort(data->mpname));
- AddPort(data->msgport);
- Permit();
-
- amp_return = TRUE;
- }
- return(amp_return);
- }
-
- /*= remMsgPort() =====================================================================-.
- || Removes message port from the port list, replies to all waiting messages and then ||
- || removes the port itself. ||
- `-====================================================================================*/
- void remMsgPort(Hotlist_Data *data)
- {
- struct Message *tmpmsg;
-
- RemPort(data->msgport);
-
- while (tmpmsg = GetMsg(data->msgport))
- ReplyMsg(tmpmsg);
-
- DeleteMsgPort(data->msgport);
- data->msgport = NULL;
- }
-
- /*= basicListerInit() ================================================================-.
- || Sends a bunch of ARexx commands to our lister to initialize it to how we want it ||
- || at the start of the program. ||
- `-====================================================================================*/
- void basicListerInit(Hotlist_Data *data,char *combuf,struct command_packet *cpp)
- {
- // Wait for the lister to finish openning, if required.
- sprintf(combuf,"lister wait %s quick",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister empty %s",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s field %s",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s display name comment",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s separate filesfirst",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s namelength %d",data->lister,HOTENTNAMELEN);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s off",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s path",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s title %s",data->lister,dgs(MSG_TITLE));
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s header (%s)",data->lister,data->config);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s label %s",data->lister,dgs(MSG_TITLE));
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s mode name",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s show #?",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s hide",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s lock state %s format %s",data->lister,"on","on");
- sendExtCmd_nr(data,combuf,cpp);
-
- // Refresh here makes format changes take effect and stops things looking
- // ugly if entries show up while being added, which they do sometimes.
- sprintf(combuf,"lister refresh %s full",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- // Add our handler.
- sprintf(combuf,"lister set %s handler %s quotes fullpath",
- data->lister,data->mpname);
- sendExtCmd_nr(data,combuf,cpp);
-
- // Trap all known commands. We still want to trap those commands which won't
- // be implimented so that we can ignore them when run, instead of them
- // attempting to run and failing on our lister.
- {
- int tnum;
- for (tnum = 0; tnum < TRAPPEDNUM; tnum++)
- {
- sprintf(combuf,"dopus addtrap %s %s",trapCmds[tnum],
- data->mpname);
- sendExtCmd_nr(data,combuf,cpp);
- }
- }
-
- // Add all the entries.
- addEntries(data,combuf,cpp);
-
- sprintf(combuf,"lister refresh %s full",data->lister);
- sendExtCmd_nr(data,combuf,cpp);
-
- // Lister setup done, Unbusy
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
- }
-
- /*= event_inactive() =================================================================-.
- || In Opus 5.5 there appears to be a bug which sometimes sends bogus "inactive" ||
- || events to handlers. In an attempt to bypass this problem, when an "inactive" ||
- || event is received it will be ignored if our lister still has our handler attached. ||
- `-====================================================================================*/
- BOOL event_inactive(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL stoploop = TRUE;
-
- sprintf(combuf,"lister query %s handler",data->lister);
- cpp->flags = COMMANDF_RESULT;
- cpp->command = combuf;
- cpp->result = NULL;
- if ((data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),cpp)) && \
- (cpp->result) && (strcmp(cpp->result,data->mpname) == 0))
- {
- // If there is a handle attached to our (old) lister, and it is our
- // handler, assume the "inactive" message was bogus as we are clearly
- // still active.
- stoploop = FALSE;
- }
-
- if (cpp->result)
- {
- FreeVec(cpp->result);
- cpp->result = NULL;
- }
-
- return(stoploop);
- }
-
- /*= event_doubleclick() ==============================================================-.
- `-====================================================================================*/
- BOOL event_doubleclick(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL stoploop = FALSE;
- ConfigListNode *clnp;
- ResNode *nrnp;
- HotEntry *he;
-
- if (he = findHotEntry(data,arg2))
- {
- if (he->type == HOTTYPE_FILE)
- {
- sprintf(combuf,"command doubleclick %s",he->path);
- sendExtCmd_nr(data,combuf,cpp);
- }
- else if (he->type == HOTTYPE_HOT)
- {
- if (strstr(arg6,"shift"))
- {
- sprintf(combuf,"command hotlist NEW CONFIG \"%s\"",he->path);
- sendExtCmd_nr(data,combuf,cpp);
- }
- else
- {
- // Store old value.
- clnp = (data->conflist);
-
- if ( (nrnp) = allocNewResNode(&data->rnd,sizeof(ConfigListNode)) )
- {
- (data->conflist) = (nrnp->rn_Mem);
- (data->conflist->rn_self) = (nrnp);
- // Store pointer to the previous config filename.
- (data->conflist->parent) = clnp;
-
- if ((data->conflist->rn) = allocNewResNode(&data->rnd,
- strlen(he->path) + 1))
- {
- strcpy(data->conflist->rn->rn_Mem,he->path);
- (data->config) = (data->conflist->rn->rn_Mem);
- notifyOff(data);
- (data->notify.nr_Name) = (data->config);
- sprintf(combuf,"lister set %s header (%s)",data->lister,
- data->config);
- sendExtCmd_nr(data,combuf,cpp);
- rereadConfig(data,combuf,cpp);
- }
- else
- {
- DisplayBeep(NULL);
- deleteResNode(&data->rnd,nrnp);
- // Restore old value.
- (data->conflist) = clnp;
- }
- }
- else
- {
- (data->conflist) = clnp;
- DisplayBeep(NULL);
- }
- }
- }
- else if (strstr(arg6,"shift"))
- {
- sprintf(combuf,"lister new %s",he->path);
- sendExtCmd_nr(data,combuf,cpp);
- }
- else
- {
- stoploop = TRUE;
- listerRead(data,combuf,cpp,he->path);
- }
- }
-
- return(stoploop);
- }
-
- /*= event_dropfrom() =================================================================-.
- `-====================================================================================*/
- BOOL event_dropfrom(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- HotEntry *he;
-
- if (0 < notHandled(data,combuf,cpp,arg3))
- {
- // Point past the initial quote.
- if (*arg2 == '"') arg2++;
- wordcpy(combuf,&arg2); // Copy the name of the first entry.
-
- if (he = findHotEntry(data,combuf))
- {
- if (he->type == HOTTYPE_FILE)
- {
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
- informUser(data,dgs(MSG_NOFILEDROP),TRUE,NULL);
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
- }
- else if (he->type == HOTTYPE_HOT)
- {
- sprintf(combuf,"command hotlist CONFIG %s LISTER %s",he->path,arg3);
- sendExtCmd_nr(data,combuf,cpp);
- }
- else
- {
- sprintf(combuf,"lister read %s \"%s\"",arg3,he->path);
- sendExtCmd_nr(data,combuf,cpp);
- }
- }
- }
-
- return(FALSE);
- }
-
- /*= event_drop() =====================================================================-.
- `-====================================================================================*/
- BOOL event_drop(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- int qnamelen;
- char *charp;
- BOOL gsr, fher;
- BOOL needsave = FALSE;
- LONG handtype;
- HotEntry *nhe;
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- if ( 0 <= (handtype = notHandled(data,combuf,cpp,arg3)) )
- {
- getWriteConfigSemaphore(data);
-
- // Point past the initial quote.
- if (*arg2 == '"') arg2++;
-
- while(*arg2) // Do all words in the list (multi-drop).
- {
- if (*arg2 == '"')
- arg2++; // If it's an empty path, skip it.
- else
- {
- // Allocate a new HotEntry structure.
- if (nhe = newHotEntry(data))
- {
- if (handtype > 0)
- {
- // For entries not from another hotlist.
-
- // Fill in the path by copying up to first quote. arg2 will
- // then point to the first letter after the second quote, if
- // there is one, or the null term.
- wordcpy(nhe->path,&arg2);
- endcpy(nhe->name,leofilepart(nhe->path),HOTENTNAMELEN);
-
- do
- {
- gsr = getString(data,dgs(MSG_NAMEFORPATH_FMT),TRUE,0,
- nhe->name,HOTENTNAMELEN,nhe->path);
- if ((gsr) && (fher = findOldEntry(data,nhe->name)))
- {
- informUser(data,dgs(MSG_NAMEDUPLIC_FMT),TRUE,0,
- nhe->name);
- }
- } while((gsr) && (fher));
- }
- else
- {
- // For entries from another hotlist.
-
- // Name is the filename.
- wordcpy(nhe->name,&arg2);
-
- // Get the path from the comment in the other hotlist.
- sprintf(combuf,"lister query %s entry \"%s\"",arg3,nhe->name);
- cpp->flags = COMMANDF_RESULT;
- cpp->command = combuf;
- cpp->result = NULL;
-
- gsr = FALSE;
-
- if ( (data->func_callback(EXTCMD_SEND_COMMAND,
- IPCDATA(data->ipc),cpp)) && \
- (cpp->result) && \
- (strlen(cpp->result) > strlen(nhe->name)) )
- {
- charp = skipSpaces((cpp->result) + strlen(nhe->name),6);
- qnamelen = strlen(charp);
- if ((charp[0] == '(') && (charp[qnamelen-1] == ')'))
- {
- strncpy(nhe->path,charp+1,qnamelen-2);
- (nhe->path)[qnamelen-2] = '\0';
- gsr = TRUE;
- }
- else
- {
- informUser(data,dgs(MSG_PATHQUERY),TRUE,0);
- }
- }
-
- if (cpp->result)
- {
- FreeVec(cpp->result);
- cpp->result = NULL;
- }
-
- // Now make sure the name is unique for our hotlist.
- // (We needed the ORIGINAL name above to query the entry)
-
- while ((gsr) && (findOldEntry(data,nhe->name)))
- {
- informUser(data,dgs(MSG_NAMEDUPLIC_FMT),TRUE,0,
- nhe->name);
- gsr = getString(data,dgs(MSG_NAMEFORPATH_FMT),TRUE,0,
- nhe->name,HOTENTNAMELEN,nhe->path);
- }
- }
-
- if ((gsr) && (nhe->name[0]))
- {
- setHotType(data,nhe); // Set the type of entry.
- needsave = TRUE; // Flag: at least one to save.
- }
- else
- {
- remHotEntry(data); // Else abort this entry.
- break; // Don't do more entries either.
- }
- }
- }
- }
-
- if (needsave)
- {
- writeConfigFile(data);
- rereadConfig(data,combuf,cpp);
- }
-
- ReleaseSemaphore(configsemaphore);
- }
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_makedir() ==================================================================-.
- `-====================================================================================*/
- BOOL event_makedir(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL gsr, fher;
- HotEntry *nhe;
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- getWriteConfigSemaphore(data);
-
- // Allocate a new HotEntry structure.
- if (nhe = newHotEntry(data))
- {
- nhe->path[0] = '\0';
- if ( (getPathString(data,dgs(MSG_PATHFORNEW_NEW),TRUE,0,
- nhe->path,HOTENTPATHLEN)) && (nhe->path[0]) )
- {
- endcpy(nhe->name,leofilepart(nhe->path),HOTENTNAMELEN);
-
- do
- {
- gsr = getString(data,dgs(MSG_NAMEFORPATH_FMT),TRUE,0,nhe->name,
- HOTENTNAMELEN,nhe->path);
- if ( (gsr) && (fher = findOldEntry(data,nhe->name)) )
- {
- informUser(data,dgs(MSG_NAMEDUPLIC_FMT),TRUE,0,nhe->name);
- }
- } while( (gsr) && (fher) );
-
- if ( (gsr) && (nhe->name[0]) )
- {
- setHotType(data,nhe); // Set the type of entry.
- writeConfigFile(data);
- rereadConfig(data,combuf,cpp);
- }
- else
- remHotEntry(data); // Else abort adding this entry.
- }
- else
- remHotEntry(data); // Else abort adding this entry.
- }
-
- ReleaseSemaphore(configsemaphore);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_delete() ===================================================================-.
- `-====================================================================================*/
- BOOL event_delete(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- LONG infotxtid;
- int wcnt;
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- getWriteConfigSemaphore(data);
-
- if ((wcnt = wordcount(arg2)) == 1)
- infotxtid = MSG_DELETE_FMT_SINGLE;
- else
- infotxtid = MSG_DELETE_FMT_PLURAL;
-
- if (informUser(data,dgs(infotxtid),TRUE,IU_CANCEL,wcnt))
- {
- BOOL needsave = FALSE;
- HotEntry *delhe;
- ResNode *delnamern;
-
- if (delnamern = allocNewResNode(&data->rnd,HOTENTNAMELEN))
- {
- // Point past the initial quote.
- if (*arg2 == '"') arg2++;
-
- while(*arg2) // Do all words in the list (multi-drop).
- {
- // Fill in the name buffer by copying up to first quote. arg2 will then
- // point to the first letter after the second quote, if there is one,
- // or the null terminator.
- wordcpy(delnamern->rn_Mem,&arg2);
-
- if (delhe = findHotEntry(data,delnamern->rn_Mem))
- {
- (delhe->deleted) = TRUE;
- needsave = TRUE;
- }
- }
-
- if (needsave)
- {
- writeConfigFile(data);
- rereadConfig(data,combuf,cpp);
- }
-
- deleteResNode(&data->rnd,delnamern);
- }
- }
-
- ReleaseSemaphore(configsemaphore);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_path() =====================================================================-.
- `-====================================================================================*/
- BOOL event_path(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL stoploop = FALSE;
-
- if (arg2[0])
- {
- stoploop = TRUE;
- listerRead(data,combuf,cpp,arg2);
- }
- else
- {
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
- rereadConfig(data,combuf,cpp);
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
- }
-
- return(stoploop);
- }
-
- /*= event_scandir_hotlist() ==========================================================-.
- `-====================================================================================*/
- BOOL event_scandir_hotlist(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- rereadConfig(data,combuf,cpp);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_snapshot() =================================================================-.
- `-====================================================================================*/
- BOOL event_snapshot(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- int x,y,w,h;
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- getWriteConfigSemaphore(data);
-
- sprintf(combuf,"lister query %s position",data->lister);
-
- cpp->flags = COMMANDF_RESULT;
- cpp->command = combuf;
- data->func_callback(EXTCMD_SEND_COMMAND,IPCDATA(data->ipc),cpp);
-
- // Backup the old values in case of failure.
- x = data->snap.x;
- y = data->snap.y;
- w = data->snap.w;
- h = data->snap.h;
-
- if (4 == sscanf(cpp->result,"%d/%d/%d/%d",&(data->snap.x),\
- &(data->snap.y),&(data->snap.w),&(data->snap.h)))
- {
- // Write new config (No point in re-reading it).
- writeConfigFile(data);
- }
- else
- {
- // Failure: Restore the old values.
- data->snap.x = x;
- data->snap.y = y;
- data->snap.w = w;
- data->snap.h = h;
- }
-
- FreeVec(cpp->result);
- cpp->result = NULL;
-
- ReleaseSemaphore(configsemaphore);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_unsnapshot() ===============================================================-.
- `-====================================================================================*/
- BOOL event_unsnapshot(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- getWriteConfigSemaphore(data);
-
- data->snap.x = data->snap.y = data->snap.w = data->snap.h = (-1);
- writeConfigFile(data); // No point re-reading the config.
-
- ReleaseSemaphore(configsemaphore);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_rename() ===================================================================-.
- `-====================================================================================*/
- BOOL event_rename(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL needsave = FALSE;
- BOOL gsr, fher;
- HotEntry *ohe;
- HotEntry *nhe;
- ResNode *orn;
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- getWriteConfigSemaphore(data);
-
- if (orn = allocNewResNode(&data->rnd,HOTENTNAMELEN))
- {
- // Point past the initial quote.
- if (*arg2 == '"') arg2++;
-
- while(*arg2) // Do all words in the list (multi-drop).
- {
- wordcpy(orn->rn_Mem,&arg2);
-
- if (ohe = findHotEntry(data,orn->rn_Mem))
- {
- if (nhe = newHotEntry(data))
- {
- strcpy(nhe->path,ohe->path);
- strcpy(nhe->name,ohe->name);
-
- // Mark the old entry as deleted so it won't show up in searches.
- // Will be left deleted unless they cancel the new entry.
- (ohe->deleted) = TRUE;
-
- if ((getPathString(data,dgs(MSG_PATHFORRENAME_FMT),TRUE,0,
- nhe->path,HOTENTPATHLEN,nhe->name)) && (nhe->path[0]))
- {
- do
- {
- gsr=getString(data,dgs(MSG_NAMEFORRENAME_FMT),TRUE,0,
- nhe->name,HOTENTNAMELEN,nhe->path);
-
- if ( (gsr) && (fher=findOldEntry(data,nhe->name)) )
- {
- informUser(data,dgs(MSG_NAMEDUPLIC_FMT),TRUE,0,
- nhe->name);
- }
- } while( (gsr) && (fher) );
-
- if ( (gsr) && (nhe->name[0]) )
- {
- setHotType(data,nhe); // Set the type of entry.
- needsave = TRUE;
- }
- else
- {
- // Else abort adding this entry.
- remHotEntry(data);
- (ohe->deleted) = FALSE; // Undelete old entry.
- break; // Don't do any more entries.
- }
- }
- else
- {
- // Else abort adding this entry.
- remHotEntry(data);
- (ohe->deleted) = FALSE; // Undelete old entry.
- break; // Don't do any more entries either.
- }
- }
- }
- }
-
- if (needsave)
- {
- writeConfigFile(data);
- rereadConfig(data,combuf,cpp);
- }
-
- deleteResNode(&data->rnd,orn);
- }
-
- ReleaseSemaphore(configsemaphore);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= event_parent() ===================================================================-.
- `-====================================================================================*/
- BOOL event_parent(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL stoploop = FALSE;
- ConfigListNode *clnp;
-
- if (data->conflist) // 'Parent' hotlist-file, if there is one.
- {
- if (strstr(arg6,"shift"))
- {
- // If shift helf down, open a new hotlist for it.
-
- sprintf(combuf,"command hotlist NEW CONFIG \"%s\"",\
- ((data->conflist->parent) ? (data->conflist->parent->rn->rn_Mem) :\
- (data->originalconfig)) );
- sendExtCmd_nr(data,combuf,cpp);
- }
- else
- {
- // If shift not held down, read it into the current lister.
-
- // Get pointer to 'parent' config file's ConfigListNode.
- clnp = (data->conflist->parent);
-
- // Turn notify off before the filename mem is deallocated and made invalid.
- notifyOff(data);
-
- // Free the old, unwanted filename memory.
- deleteResNode(&data->rnd,data->conflist->rn);
- // Free the old, unwanted ConfigListNode.
- deleteResNode(&data->rnd,data->conflist->rn_self);
-
- // Make the parent of the 'old' node the top-level node.
- (data->conflist) = clnp;
-
- // Setup the filenames.
- if (data->conflist)
- {
- // If there is still a parent config-file to go to, use it.
- (data->config) = (data->conflist->rn->rn_Mem);
- (data->notify.nr_Name) = (data->config);
- }
- else
- {
- // If there's no parent config-file, use the original one.
- (data->config) = (data->originalconfig);
- }
-
- // Update the title.
- sprintf(combuf,"lister set %s header (%s)",data->lister,data->config);
- sendExtCmd_nr(data,combuf,cpp);
- // Read in the 'new' config file.
- rereadConfig(data,combuf,cpp);
- }
- }
- else if (data->parent[0]) // Or 'real' parent dir, if there is one.
- {
- if (strstr(arg6,"shift"))
- {
- sprintf(combuf,"lister new %s",data->parent);
- sendExtCmd_nr(data,combuf,cpp);
- }
- else
- {
- stoploop = TRUE;
- listerRead(data,combuf,cpp,data->parent);
- }
- }
- else // Otherwise just beep.
- DisplayBeep(NULL);
-
- return(stoploop);
- }
-
- /*= event_duplicate() ================================================================-.
- `-====================================================================================*/
- BOOL event_duplicate(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
- char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6)
- {
- BOOL needsave = FALSE;
- BOOL gsr, fher;
- HotEntry *ohe;
- HotEntry *nhe;
- ResNode *orn;
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"on");
- sendExtCmd_nr(data,combuf,cpp);
-
- getWriteConfigSemaphore(data);
-
- if (orn = allocNewResNode(&data->rnd,HOTENTNAMELEN))
- {
- // Point past the initial quote.
- if (*arg2 == '"') arg2++;
-
- while(*arg2) // Do all words in the list (multi-drop).
- {
- wordcpy(orn->rn_Mem,&arg2);
-
- if (ohe = findHotEntry(data,orn->rn_Mem))
- {
- if (nhe = newHotEntry(data))
- {
- strcpy(nhe->path,ohe->path);
- strcpy(nhe->name,ohe->name);
-
- if ((getPathString(data,dgs(MSG_PATHFORNEW),TRUE,0,
- nhe->path,HOTENTPATHLEN)) && (nhe->path[0]))
- {
- do
- {
- gsr=getString(data,dgs(MSG_NAMEFORPATH_FMT),TRUE,0,
- nhe->name,HOTENTNAMELEN,nhe->path);
-
- if ( (gsr) && (fher=findOldEntry(data,nhe->name)) )
- {
- informUser(data,dgs(MSG_NAMEDUPLIC_FMT),TRUE,0,
- nhe->name);
- }
- } while( (gsr) && (fher) );
-
- if ( (gsr) && (nhe->name[0]) )
- {
- setHotType(data,nhe); // Set the type of entry.
- needsave = TRUE;
- }
- else
- {
- // Else abort adding this entry.
- remHotEntry(data);
- break; // Don't do any more entries.
- }
- }
- else
- {
- // Else abort adding this entry.
- remHotEntry(data);
- break; // Don't do any more entries either.
- }
- }
- }
- }
-
- if (needsave)
- {
- writeConfigFile(data);
- rereadConfig(data,combuf,cpp);
- }
-
- deleteResNode(&data->rnd,orn);
- }
-
- ReleaseSemaphore(configsemaphore);
-
- sprintf(combuf,"lister set %s busy %s wait",data->lister,"off");
- sendExtCmd_nr(data,combuf,cpp);
-
- return(FALSE);
- }
-
- /*= getConfigSemaphore() =============================================================-.
- || Get a lock on the configfile semaphore, showing a progress window if it isn't ||
- || immediately obtainable. obtype should be GCS_SHARED or GCS_EXCLUSIVE. ||
- || The semaphore returned should be freed with ReleaseSemaphore as usual. ||
- `-====================================================================================*/
- void getConfigSemaphore(Hotlist_Data *data,short obtype)
- {
- APTR progwin;
- struct Window *win;
- struct Screen *screen;
- LONG goddit;
-
- if (win = getListerWindow(data))
- screen = NULL;
- else
- screen = getDOpusScreen(data);
-
- if (obtype == GCS_SHARED)
- goddit = AttemptSemaphoreShared(configsemaphore);
- else
- goddit = AttemptSemaphore(configsemaphore);
-
- if ( !(goddit) )
- {
- progwin = OpenProgressWindowTags(
- TAGIF(win,PW_Window), win,
- TAGIF((!win) && screen,PW_Screen), screen,
- PW_Title, dgs(MSG_TITLE),
- PW_FileName, dgs(MSG_SEMWAIT),
- PW_Flags, PWF_FILENAME,
- TAG_END);
-
- if (obtype == GCS_SHARED)
- ObtainSemaphoreShared(configsemaphore);
- else
- ObtainSemaphore(configsemaphore);
-
- if (progwin)
- CloseProgressWindow(progwin);
- }
- }
-
- /*= getWriteConfigSemaphore() ========================================================-.
- || This routine first gets exclusive access to the config file semaphore and then ||
- || re-reads the config file if file notification reports that it has changed. ||
- || You should call this routine to get your semaphore lock prior to changing any ||
- || config file data and writting a new config file. ||
- || I repeat: PRIOR TO CHANGING ANY CONFIG FILE DATA -- Don't just call it right ||
- || before calling writeConfigFile() as if the config file has changed it'll be ||
- || re-read, replacing any changes you have just made, and then written out again ||
- || exactly the same. ||
- || You should release the semaphore lock after you're finished writting with a call ||
- || to ReleaseSemaphore() -- writeConfigFile() won't do this for you! ||
- ||------------------------------------------------------------------------------------||
- || Currently it doesn't re-read the changed file as the notification routines are yet ||
- || to be written. I haven't even decided exactly how they will work. ||
- `-====================================================================================*/
- void getWriteConfigSemaphore(Hotlist_Data *data)
- {
- // First, get us exclusive access to the config file.
- getConfigSemaphore(data,GCS_EXCLUSIVE);
-
- // Now, if the file has changed, re-read.
- if ((SetSignal(0,0)) & (data->notsigmask))
- {
- SetSignal(0,data->notsigmask);
- // readConfigFile() won't get it's own semaphore lock as 2nd argument TRUE.
- readConfigFile(data,TRUE);
- }
- }
-
- /*= notifyOn() =======================================================================-.
- || Routine to handle turning on notification on the config file. Will set ||
- || data->notifyon to TRUE if it succeeds. Will not start another notification ||
- || request if data->notifyon indicates we already have one. As some filesystems do ||
- || not support notification, notification may still be off after this call. ||
- || The signal bit used for notification will be cleared. ||
- `-====================================================================================*/
- void notifyOn(Hotlist_Data *data)
- {
- // Unless notification already on, attempt to turn it on.
- if (!(data->notifyon))
- {
- // If the signal is set, clear it.
- // We could just clear it, but the autodocs/RKRM discourage it.
- if ((SetSignal(0,0)) & (data->notsigmask))
- SetSignal(0,data->notsigmask);
-
- (data->notifyon) = StartNotify(&data->notify);
- }
- }
-
- /*= notifyOff() ======================================================================-.
- || If data->notifyon indicates we have a notification request this routine will turn ||
- || it off and set data->notifyon to FALSE. ||
- `-====================================================================================*/
- void notifyOff(Hotlist_Data *data)
- {
- if (data->notifyon)
- {
- EndNotify(&data->notify);
- (data->notifyon) = FALSE;
- }
- }
-
- /*= SkipSpaces() =====================================================================-.
- || Returns pointer to just after the nth space in the string. ||
- || Returns pointer to the NULL at the end of the string if not enough spaces. ||
- `-====================================================================================*/
- char *skipSpaces(char *text,int numspac)
- {
- if (text)
- {
- while (*text && numspac)
- {
- if (*(text++) == ' ')
- numspac--;
- }
- }
- return text;
- }
-